﻿package kliment.utils {
	import kliment.math.Calc;

	/**
	 * ...
	 * @author	Kliment
	 * @version	1.2.7
	 *
	 * class name: kliment.utils._String
	 */
	public class _String {
		static private const PATTERN_FLAGS:String = 'gi';
		static private const SPECIALCHARS:Array = [['&', '&amp;'],['<', '&lt;'], ['>', '&gt;'], ['"', '&quot;'], ["'", '&apos;']];
		static public const DIR_DELIMER:String = '/';
		static public const PROTOCOL_DELIMER:String = ':' + DIR_DELIMER + DIR_DELIMER;

		/**
		 *
		 */
		static public function addZero(value:Number, countZero:Number = 2):String {
			var valueAbs:Number = Math.abs(value);
			var leftLenght:Number = String(valueAbs >> 0).length;
			var preffix:String = repeat('0', countZero - leftLenght);
			if (value < 0)
				preffix = '-' + preffix;
			return preffix + valueAbs;
		}

		/**
		 *
		 */
		static public function addZeroNumberStr(value:String, countZero:Number = 2):String {
			var valueAbs:String = value;
			var leftLenght:Number = value.length;
			var preffix:String = repeat('0', countZero - leftLenght);
			/*if (value < 0)
				preffix = '-' + preffix;*/
			return preffix + valueAbs;
		}

		/**
		 * Insert substring in to string.
		 */
		static public function insert(source:String, position:Number, repl:String):String {
			return source.substring(0, position) + repl + source.substring(position, source.length-1);
		}

		/**
		 * Dublicate string.
		 */
		static public function repeat(str:String, count:Number):String {
			var result:String = '';
			while (count-- > 0)
				result += str;
			return result;
		}

		/**
		 * Set the size of the fractional part.
		 */
		static public function decimalFractions(value:Number, fractionsPart:uint):String {
			var right:Number = Calc.decimalPart(value, fractionsPart);
			var rightStr:String;
			var rightLength:Number;
			if (right > 0) {
				rightStr = String(right);
				rightStr = rightStr.substring(1, rightStr.length);
				rightLength = rightStr.length - 1;
			} else {
				rightStr = '.';
				rightLength = 0;
			}
			return String(Math.floor(value) + rightStr + repeat('0', fractionsPart - rightLength));
		}

		/**
		 * Divide string of the number on the groups
		 */
		static public function numberGroups(value:Number, delimer:String, decimalPart:Number):String {
			delimer = delimer || ' ';
			var valueAbs:Number = Math.abs(value);
			var decimalPartStr:String = decimalFractions(Calc.decimalPart(valueAbs, decimalPart), decimalPart).substring(2, decimalPartStr.length);
			if (decimalPartStr.length > 0)
				decimalPartStr = '.' + decimalPartStr;
			var numString:String = String(Math.floor(valueAbs));
			var length:Number = numString.length;
			var arrayString:Array = new Array();
			var start:Number;
			while (length > 0) {
				start = Math.max(0, length - 3);
				arrayString.unshift(numString.substring(start, length));
				length = start;
			}
			return (valueAbs != value?'-':'') + arrayString.join(delimer) + decimalPartStr;
		}

		/**
		 * Make a string's first character uppercase
		 *
		 * @param	str The input string.
		 * @return	Returns the resulting string.
		 */
		static public function ucfirst(str:String):String {
			return getFirstChar(str).toUpperCase() + str.substring(1, str.length);
		}

		/**
		 * Make a string's first character uppercase, rest lowercase
		 *
		 * @param	str The input string.
		 * @return	Returns the resulting string.
		 */
		static public function ucfirst_lcrest(str:String):String {
			return ucfirst(str.toLowerCase());
		}

		/**
		 * Make a string's first character lowercase
		 *
		 * @param	str The input string.
		 * @return	Returns the resulting string.
		 */
		static public function lcfirst(str:String):String {
			return getFirstChar(str).toLowerCase() + str.substring(1, str.length);
		}

		/**
		 * Make a string's first character lowercase, rest uppercase
		 *
		 * @param	str The input string.
		 * @return	Returns the resulting string.
		 */
		static public function lcfirst_ucrest(str:String):String {
			return lcfirst(str.toUpperCase());
		}

		/**
		 * Get first char from string;
		 *
		 * @param	str The input string.
		 * @return	Returns the resulting string
		 */
		static public function getFirstChar(str:String):String {
			return str.substring(0, 1);
		}

		static public function htmlspecialchars(value:String):String {
			for each (var item:Array in SPECIALCHARS)
				value = value.replace(new RegExp(item[0], PATTERN_FLAGS), item[1]);
			return value;
		}

		static public function htmlspecialchars_decode(value:String):String {
			var length:int = SPECIALCHARS.length;
			for(var item:* in SPECIALCHARS)
				value = value.replace(new RegExp(SPECIALCHARS[item][1], PATTERN_FLAGS), SPECIALCHARS[item][0]);
			return value;
		}

		static public function urlDirName(value:String):String {
			var startIndex:int = value.indexOf(PROTOCOL_DELIMER + DIR_DELIMER);
			if (startIndex > -1) {
				startIndex += 4;
			} else if ((startIndex = value.indexOf(PROTOCOL_DELIMER)) > -1) {
				startIndex += 3;
			} else {
				startIndex = 0;
			}
			return value.substring(startIndex, value.lastIndexOf(DIR_DELIMER, value.length - 2)) + DIR_DELIMER;
		}

		static public function urlHomeName(value:String):String {
			return urlDirName(value).substring(0, value.indexOf(DIR_DELIMER) + 1) + DIR_DELIMER;
		}

		static public function urlBaseName(value:String):String {
			return value.substring(value.lastIndexOf(DIR_DELIMER) + 1, value.length);
		}

		static public function urlProtocol(value:String):String {
			return value.substr(0, value.indexOf(PROTOCOL_DELIMER));
		}
	}

}